<HTML>
<HEAD>
<TITLE>Defining Traits and Facets for User-Defined Types</TITLE>
<LINK REL=StyleSheet HREF="../rw.css" TYPE="text/css" TITLE="Rogue Wave Standard Stylesheet"></HEAD>
<BODY BGCOLOR=#FFFFFF>
<A HREF="41-1.html"><IMG SRC="images/bprev.gif" WIDTH=20 HEIGHT=21 ALT="Previous file" BORDER=O></A><A HREF="noframes.html"><IMG SRC="images/btop.gif" WIDTH=56 HEIGHT=21 ALT="Top of Document" BORDER=O></A><A HREF="booktoc.html"><IMG SRC="images/btoc.gif" WIDTH=56 HEIGHT=21 ALT="Contents" BORDER=O></A><A HREF="tindex.html"><IMG SRC="images/bindex.gif" WIDTH=56 HEIGHT=21 ALT="Index page" BORDER=O></A><A HREF="41-3.html"><IMG SRC="images/bnext.gif" WIDTH=25 HEIGHT=21 ALT="Next file" BORDER=O></A><DIV CLASS="DOCUMENTNAME"><B>Rogue Wave C++ Standard Library User's Guide</B></DIV>
<H2>41.2 Defining Traits and Facets for User-Defined Types</H2>
<A NAME="idx967"><!></A>
<P>A user-defined type requires its own traits class, its own code conversion facet, and its own character classification facet. The traits class defines a conversion <SAMP>state_type</SAMP> and also defines operations such as copying arrays of the type and comparing arrays.   The code conversion facet provides conversion to and from simple <SAMP>char</SAMP>s.   The <SAMP>ctype</SAMP> facet provides character classification and manipulation routines, including the method for converting the new type to and from simple <SAMP>char</SAMP>s.</P>
<A NAME="idx968"><!></A>
<P>The following code shows a traits class declaration for <SAMP>Echar</SAMP>:</P>

<UL><PRE>
struct Etraits 
{
  typedef Echar                  char_type;
  typedef long                   int_type;

  typedef std::streamoff         off_type;
  typedef std::mbstate_t         state_type;
  typedef std::fpos&lt;state_type&gt;  pos_type;

  static void assign (char_type&amp; c1, const char_type&amp; c2);
  static bool eq(const char_type&amp; c1,const char_type&amp; c2);
  static bool lt (const char_type&amp; c1, const char_type&amp; c2);
  static int compare (const char_type* s1, const char_type* s2,
                      std::size_t n);
  static std::size_t length(const char_type *s);
  static const char_type*
      find (const char_type* s, int n, const char_type&amp; a);
  static char_type* move (char_type* s1, const char_type* s2,
                          std::size_t n);
  static char_type* copy(char_type *dst,const char_type *src,
                         std::size_t n);
  static char_type* assign (char_type* s, std::size_t n, 
                            const char_type&amp; a);
  static int_type not_eof(const int_type&amp; c);
  static char_type to_char_type(const int_type&amp; c);
  static int_type to_int_type(const char_type&amp; c);
  static bool eq_int_type(const int_type&amp; c1,const int_type&amp; c2);
  static state_type get_state(pos_type pos);
  static int_type eof();
};
</PRE></UL>
<P>See the <A HREF="../stdlibref/noframes.html"><I>Standard C++ Library Module Reference Guide</I></A> section on <A HREF="../stdlibref/char-traits.html">char_traits</A> for a complete description of the member functions in a traits class.</P>
<P>To create a new code conversion facet, you must inherit from the <SAMP>std::codecvt</SAMP> template and then override some or all the protected virtual functions. Iostreams calls the protected functions through the public interface defined for <SAMP>std::codecvt</SAMP>. You must also provide a constructor taking a single <SAMP>std::size_t</SAMP> argument, and initialize <SAMP>codecvt</SAMP> with that argument.</P>
<A NAME="idx969"><!></A>
<P>A code conversion facet for <SAMP>Echar</SAMP> has a declaration that looks like this:</P>

<UL><PRE>
class Ecodecvt : public std::codecvt&lt;Echar,char,Estate&gt;
{
  public:
       explicit Ecodecvt (std::size_t refs = 0)
           : std::codecvt&lt;Echar,char,Estate&gt;(refs) { }

  protected:

          virtual result do_out(Estate&amp; state, const Echar* from,
                                const Echar* from_end, 
                                const Echar*&amp; from_next,
                                char* to, char* to_limit,
                                char*&amp; to_next) const;
         virtual result do_in(Estate&amp; state,
                              const char* from,
                              const char* from_end, 
                              const char*&amp; from_next,
                              Echar* to, Echar* to_limit,
                              Echar*&amp; to_next) const;
         virtual result do_unshift(Estate&amp; state,
                                   char* to, char* to_limit,
                                   char*&amp; to_next) const;
         virtual int do_encoding() const throw();
         virtual bool do_always_noconv() const throw();
         virtual int do_length(Estate&amp; state, const char* from,
                               const char* end, size_t maxm) const;
         virtual int do_max_length() const throw();
};
</PRE></UL>
<P>See <A HREF="40.html">Chapter&nbsp;40</A> on defining a code conversion facet for more details. Also see the <A HREF="../stdlibref/noframes.html"><I>Standard C++ Library Module Reference Guide</I></A> section on <A HREF="../stdlibref/codecvt.html">codecvt</A> for a complete description of member functions.</P>
<P>To create a character classification facet, you must inherit from the <SAMP>std::ctype</SAMP> template and provide implementations for all protected virtual functions. You must also provide a constructor taking a single <SAMP>std::size_t</SAMP> argument, and initialize <SAMP>std::ctype</SAMP> with that argument.</P>
<P>Note that the <SAMP>widen()</SAMP> functions define conversions from simple <SAMP>char</SAMP>s to the user-defined character type, and the narrow function provides conversions from the user-defined type to simple <SAMP>char</SAMP>s.</P>
<A NAME="idx970"><!></A>
<P>A character classification facet for <SAMP>Echar</SAMP> has a declaration that looks like this:</P>

<UL><PRE>
class Ectype : public std::ctype&lt;Echar&gt;
{
     public:
       typedef Echar char_type;
       explicit Ectype (std::size_t refs = 0) : 
           std::ctype&lt;Echar&gt;(refs) { }     // must pass refs onto
                                           // the ctype constructor

     protected:

       virtual bool do_is(mask m, Echar c) const;
       virtual const Echar* do_is(
                                  const Echar* low,
                                  const Echar* high,
                                  mask* vec) const;
       virtual const Echar* do_scan_is(
                                       mask m, const Echar* low,
                                       const Echar* high) const;
       virtual const Echar* do_scan_not(
                                        mask m, const Echar* low,
                                        const Echar* high) const;
       virtual Echar        do_toupper(Echar e)  const;
       virtual const Echar* do_toupper(Echar* low,
                                       const Echar* high) const;
       virtual Echar        do_tolower(Echar)  const;
       virtual const Echar* do_tolower(Echar* low,
                                       const Echar* high) const;
       virtual Echar        do_widen(char) const;
       virtual const char*  do_widen(const char* lo,
                                     const char* hi,
                                     Echar* dest) const;
       virtual char         do_narrow(Echar, char dfault) const;
       virtual const Echar* do_narrow(const Echar* lo,
                                      const Echar* hi,char dfault,
                                      char* dest) const;

};
</PRE></UL>

<BR>
<HR>
<A HREF="41-1.html"><IMG SRC="images/bprev.gif" WIDTH=20 HEIGHT=21 ALT="Previous file" BORDER=O></A><A HREF="noframes.html"><IMG SRC="images/btop.gif" WIDTH=56 HEIGHT=21 ALT="Top of Document" BORDER=O></A><A HREF="booktoc.html"><IMG SRC="images/btoc.gif" WIDTH=56 HEIGHT=21 ALT="Contents" BORDER=O></A><A HREF="tindex.html"><IMG SRC="images/bindex.gif" WIDTH=56 HEIGHT=21 ALT="Index page" BORDER=O></A><A HREF="41-3.html"><IMG SRC="images/bnext.gif" WIDTH=20 HEIGHT=21 ALT="Next file" BORDER=O></A></BODY>
</HTML>
